#include "absl/strings/string_view.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/protobuf/meta_graph.pb.h"
#include <chrono>
#include <iostream>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <numeric>

const static std::string pb_root = "./test_model.pb";

int main()
{
    std::string haha("haha");
    int a = 0;
    using namespace tensorflow;
    //auto session = NewSession(SessionOptions());
    Session* session;
    TF_CHECK_OK(NewSession(SessionOptions(), &session));

    GraphDef graph_def;
    //MetaGraphDef meta_graph_def;
    TF_CHECK_OK(ReadBinaryProto(Env::Default(), pb_root, &graph_def));
    //TF_CHECK_OK(ReadBinaryProto(Env::Default(), meta_graph_root, &meta_graph_def));
    TF_CHECK_OK(session->Create(graph_def));
    //TF_CHECK_OK(session->Create(meta_graph_def.graph_def()));
    auto start1 = std::chrono::steady_clock::now();

    std::fstream input_file("train_data.txt");

    TF_CHECK_OK(session->Run({}, {}, {"init_all_tables"}, nullptr));
    TF_CHECK_OK(session->Run({}, {}, {"init_all_vars_op"}, nullptr));

    std::vector<int>     boss_position_vector;
    std::vector<int>     boss_city_vector;
    std::vector<int>     geek_position_vector;
    std::vector<int>     geek_city_vector;
    std::vector<float>   deal_type_vector;
    std::vector<float>   jl_vector;
    std::vector<float>   jh_vactor;
    std::vector<int>     job_workyears_vector;
    std::vector<int>     job_degree_vector;
    std::vector<int>     geek_gender_vector;
    std::vector<int>     geek_apply_status_vector;
    std::vector<float>   el_vector;
    std::vector<float>   eh_vector;
    std::vector<int>     boss_cmp_level_vector;
    std::vector<int>     title_type_vector;

    int loss_len = 1000;
    int len = 1000;
    float loss_result = 0;
    for (int i = 1; i < 1951298; ++i) {
        std::string line;
        getline(input_file, line);
        int count = 0;
        std::string data;
        for(int j=0; j<line.size(); j++){
            if(line[j] != 9) {
                data = data + line[j];
            }else{
                if(count==0){
                    int temp_int = atoi(data.c_str());
                    boss_position_vector.push_back(temp_int);
                    count++;
                }else if(count==1){
                    int temp_int = atoi(data.c_str());
                    boss_city_vector.push_back(temp_int);
                    count++;
                }else if(count==2){
                    int temp_int = atoi(data.c_str());
                    geek_position_vector.push_back(temp_int);
                    count++;
                }else if(count==3){
                    int temp_int = atoi(data.c_str());
                    geek_city_vector.push_back(temp_int);
                    count++;
                }else if(count==4){
                    if(data=="success"){
                        float a = 1;
                        deal_type_vector.push_back(a);
                    }else{
                        float b = 0;
                        deal_type_vector.push_back(b);
                    }
                    count++;
                }else if(count==5){
                    float temp_float = atof(data.c_str());
                    jl_vector.push_back(temp_float);
                    count++;
                }else if(count==6){
                    float temp_float = atof(data.c_str());
                    jh_vactor.push_back(temp_float);
                    count++;
                }else if(count==7){
                    int temp_int = atoi(data.c_str());
                    job_workyears_vector.push_back(temp_int);
                    count++;
                }else if(count==8){
                    int temp_int = atoi(data.c_str());
                    job_degree_vector.push_back(temp_int);
                    count++;
                }else if(count==9){
                    int temp_int = atoi(data.c_str());
                    geek_gender_vector.push_back(temp_int);
                    count++;
                }else if(count==10){
                    int temp_int = atoi(data.c_str());
                    geek_apply_status_vector.push_back(temp_int);
                    count++;
                }else if(count==11){
                    float temp_float = atof(data.c_str());
                    el_vector.push_back(temp_float);
                    count++;
                }else if(count==12){
                    float temp_float = atof(data.c_str());
                    eh_vector.push_back(temp_float);
                    count++;
                }else if(count==13){
                    int temp_int = atoi(data.c_str());
                    boss_cmp_level_vector.push_back(temp_int);
                    count++;
                }
                data = "";
            }
        }
        int temp_int = atoi(data.c_str());
        title_type_vector.push_back(temp_int);
        count++;
        data = "";
        if(i%len==0){
            Tensor input_boss_position(DT_INT64, TensorShape({len,}));
            auto aa1 = input_boss_position.flat<int64>().data();
            copy_n(boss_position_vector.begin(), len, aa1);
            Tensor input_boss_city(DT_INT64, TensorShape({len,}));
            auto aa2 = input_boss_city.flat<int64>().data();
            copy_n(boss_city_vector.begin(), len, aa2);
            Tensor input_geek_position(DT_INT64, TensorShape({len,}));
            auto aa3 = input_geek_position.flat<int64>().data();
            copy_n(geek_position_vector.begin(), len, aa3);
            Tensor input_geek_city(DT_INT64, TensorShape({len,}));
            auto aa4 = input_geek_city.flat<int64>().data();
            copy_n(geek_city_vector.begin(), len, aa4);
            Tensor input_job_workyears(DT_INT64, TensorShape({len,}));
            auto aa5 = input_job_workyears.flat<int64>().data();
            copy_n(job_workyears_vector.begin(), len, aa5);
            Tensor input_job_degree(DT_INT64, TensorShape({len,}));
            auto aa6 = input_job_degree.flat<int64>().data();
            copy_n(job_degree_vector.begin(), len, aa6);
            Tensor input_geek_gender(DT_INT64, TensorShape({len,}));
            auto aa7 = input_geek_gender.flat<int64>().data();
            copy_n(geek_gender_vector.begin(), len, aa7);
            Tensor input_geek_apply_status(DT_INT64, TensorShape({len,}));
            auto aa8 = input_geek_apply_status.flat<int64>().data();
            copy_n(geek_apply_status_vector.begin(), len, aa8);
            Tensor input_boss_cmp_level(DT_INT64, TensorShape({len,}));
            auto aa9 = input_boss_cmp_level.flat<int64>().data();
            copy_n(boss_cmp_level_vector.begin(), len, aa9);
            Tensor input_title_type(DT_INT64, TensorShape({len,}));
            auto aa10 = input_title_type.flat<int64>().data();
            copy_n(title_type_vector.begin(), len, aa10);
            Tensor input_jl(DT_FLOAT, TensorShape({len,}));
            auto bb1 = input_jl.flat<float>().data();
            copy_n(jl_vector.begin(), len, bb1);
            Tensor input_jh(DT_FLOAT, TensorShape({len,}));
            auto bb2 = input_jh.flat<float>().data();
            copy_n(jh_vactor.begin(), len, bb2);
            Tensor input_el(DT_FLOAT, TensorShape({len,}));
            auto bb3 = input_el.flat<float>().data();
            copy_n(el_vector.begin(), len, bb3);
            Tensor input_eh(DT_FLOAT, TensorShape({len,}));
            auto bb4 = input_eh.flat<float>().data();
            copy_n(eh_vector.begin(), len, bb4);
            Tensor output_deal_type(DT_FLOAT, TensorShape({len,}));
            auto bb5 = output_deal_type.flat<float>().data();
            copy_n(deal_type_vector.begin(), len, bb5);


            //std::cout << "input_y_ is : " << input_y_.matrix<float>() << std::endl;
            //    for(int i=0;i<input_x.flat<float>().size(); i++){
            //        std::cout << input_x.flat<float>().data()[i] << " ";
            //    }

            //feed_dict
            std::vector<std::pair<string, tensorflow::Tensor>> inputs =
            {
                {"125"     , input_boss_position    },
                {"label"   , output_deal_type       },
                {"128"     , input_boss_city        },
                {"118"     , input_geek_position    },
                {"120"     , input_geek_city        },
                {"174"     , input_jl               },
                {"177"     , input_jh               },
                {"130"     , input_job_workyears    },
                {"171"     , input_job_degree       },
                {"204"     , input_geek_gender      },
                {"217"     , input_geek_apply_status},
                {"289"     , input_el               },
                {"292"     , input_eh               },
                {"391"     , input_boss_cmp_level   },
                {"355"     , input_title_type       },
            };

            //train data
            TF_CHECK_OK(session->Run(inputs, {}, { "train_op" }, nullptr));

            boss_position_vector.clear();
            boss_city_vector.clear();
            geek_position_vector.clear();
            geek_city_vector.clear();
            deal_type_vector.clear();
            jl_vector.clear();
            jh_vactor.clear();
            job_workyears_vector.clear();
            job_degree_vector.clear();
            geek_gender_vector.clear();
            geek_apply_status_vector.clear();
            el_vector.clear();
            eh_vector.clear();
            boss_cmp_level_vector.clear();
            title_type_vector.clear();

            std::vector<tensorflow::Tensor> loss;
            TF_CHECK_OK(session->Run(inputs, {"loss"}, {}, &loss));
            //std::cout << loss[0].flat<float>().data()[0] << std::endl;
            std::vector<float> loss_vector;
            float loss_temp = 0;
            for(int i=0; i<len; i++){
                loss_temp += loss[0].flat<float>().data()[i];
//                loss_vector.push_back(loss[0].flat<float>().data()[i]);
            }
            loss_temp = loss_temp/len;
//            float loss_vector_sum = 0;
//            for (auto i : loss_vector){
//                loss_vector_sum += i;
//            }
//            std::cout << "loss_vector means is : " << loss_vector_sum/loss_vector.size() << std::endl;
            //std::cout << "loss is : " << loss_temp << std::endl;
//            std::cout << "loss is : " << loss[0].flat<float>().data()[1] << std::endl;
            loss_result += loss_temp;
            if(i%loss_len==0){
                loss_result = loss_result/(loss_len/len);
                std::cout << "loss is : " << loss_result << std::endl;
                loss_result = 0;
            }
        }
    }

    auto end1 = std::chrono::steady_clock::now();
    std::chrono::duration<double, std::micro> elapsed = end1 - start1; // std::micro 表示以微秒为时间单位
    std::cout << "!!!!!!!!!!!" << std::endl;
    std::cout<< "time: "  << elapsed.count() << "us" << std::endl;
    std::cout<< "time: "  << elapsed.count()/1000000 << "s" << std::endl;

    session->Close();

    return 0;
}